#!/usr/bin/env python

from errno import ENOENT

from fuse import FUSE, FuseOSError, Operations, LoggingMixIn
from moodlefuse.modules.courses.files import Courses
from api import API
from settings import CACHE_FOLDER

from sys import argv, exit
import os
import shutil

class Moodle(Operations, LoggingMixIn):

    def __init__(self, username, password):
        self.files = {}

        api = API(username, password)
        try:
            api.login()
            self.files['/'] = Courses(api, None, None)
        except API.InvalidCredentials, ie:
            print ie.value

    def init(self, path):
        if not os.path.exists(CACHE_FOLDER):
            os.makedirs(CACHE_FOLDER)

    def destroy(self, path):
        shutil.rmtree(CACHE_FOLDER)

    def chmod(self, path, mode):
        print "chmod %s - %s" % (path, mode)
        file = self.get_base_file(path)
        file.attrs['st_mode'] &= 0770000
        file.attrs['st_mode'] |= mode

        return 0

    def chown(self, path, uid, gid):
        file = self.get_base_file(path)
        file.attrs['st_uid'] = uid
        file.attrs['st_gid'] = gid
    
    def create(self, path, mode, fi=None):
        head, tail = os.path.split(path)
        directory = self.get_base_file(head)
        directory.create_file(tail, mode)

        return 1

    def getattr(self, path, fh=None):
        return self.get_base_file(path).attrs

    def get_base_file(self, path):
        file = self.files['/']
        
        paths = path.split('/')
        for path_part in paths:
            if not path_part:
                continue

            try:
                file = file.get_files()[path_part]
            except KeyError:
                raise FuseOSError(ENOENT)
            except TypeError:
                raise FuseOSError(ENOENT)

        return file
    
    def open(self, path, flags):
        file = self.get_base_file(path)
        file.attrs['st_nlink'] += 1
        return file.attrs['st_nlink']
    
    def read(self, path, size, offset, fh):
        file = self.get_base_file(path)
        return file.read(size, offset)

    def readdir(self, path, fh):
        files = self.get_base_file(path).files
        return ['.', '..'] + [file_name for file_name in files.keys()]
    
    def release(self, path, fh):
        file = self.get_base_file(path)
        file.attrs['st_nlink'] -= 1
        file.sync()
        return 0    

    def rename(self, old_path, new_path):
        file = self.get_base_file(old_path)
        name = file.rename(new_path)

        head, tail = os.path.split(old_path)
        directory = self.get_base_file(head)
        del directory.files[tail]
        directory.files[name] = file
    
    def statfs(self, path):
        return dict(f_bsize=512, f_blocks=4096, f_bavail=2048)
        
    def truncate(self, path, length, fh=None):
        file = self.get_base_file(path)
        file.truncate(length)

    def unlink(self, path):
        head, file_name = os.path.split(path)
        directory = self.get_base_file(head)
        del directory.files[file_name]

    def write(self, path, data, offset, fh):
        file = self.get_base_file(path)
        file.write(data, offset)
        return len(data)

if __name__ == "__main__":

    if len(argv) != 4:
        print 'usage: %s <mountpoint> username password' % argv[0]
        exit(1)

    username = argv[2]
    password = argv[3]

    fuse = FUSE(Moodle(username, password), argv[1], foreground=True)